﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using XXF.BaseService.ServiceCenter.Client.Provider;
using XXF.BaseService.ServiceCenter.SystemRuntime;
using ZooKeeperNet;

namespace XXF.BaseService.ServiceCenter.ZK
{
    public class ZkNodeInfo
    {
        public string ServiceNameSpace { get; set; }
        public long SessionId { get; set; }
    }
    public class ZKCenterWatch : ZKBase
    {
        private ClientContext Context;
        private CancellationTokenSource _cancelSource;
        private AutoResetEvent autoevent;
        private string _servicenamespace;
        private long _sessionid;
        private int _serviceid;
        private bool isdisposeing;
        private Func<ZkNodeInfo> _nodeRemoved;

        public void Register(CancellationTokenSource cancelsource, ClientContext context, Func<ZkNodeInfo> NodeRemoved)
        {
            Context = context;
            _serviceid = context.ServiceModel.id;
            _nodeRemoved = NodeRemoved;
            _cancelSource = cancelsource;
            autoevent = new AutoResetEvent(false);

            System.Threading.Tasks.Task.Factory.StartNew(() =>
            {
                WatchNodePathRun(_servicenamespace, _sessionid);
            }, cancelsource.Token);


        }

        private void WatchNodePathRun(string servicenamespace, long sessionid)
        {
            while (!_cancelSource.IsCancellationRequested && isdisposeing == false)
            {
                try
                {
                    var zk = GetZookeeper();
                    this.CreateRoot();
                    var list = zk.GetChildren(this.GetServicePath(_serviceid), true);
                    autoevent.WaitOne();
                }
                catch (Exception exp)
                {
                    System.Threading.Thread.Sleep(SystemParamConfig.ZK_RegisterNode_FailConnect_ReConnect_Every_Time * 1000);
                    if (isdisposeing == false) { }
                }

            }
            Dispose();
        }

        public override void Process(WatchedEvent @event)
        {
            if (isdisposeing == true)
                return;
            var zk = GetZookeeper();
            try
            {
                if (null != @event.Path && @event.Type == EventType.NodeChildrenChanged)
                {
                    var data = zk.GetChildren(@event.Path, false);
                    data.ToList().ForEach((a) => Context.NodeModels.Remove(Context.NodeModels.FirstOrDefault(s => s.sessionid == Convert.ToInt64(a))));
                }
            }

            //try
            //{
            //    var nodeinfo = this.GetPathInfo(@event.Path);
            //    if (nodeinfo != null && nodeinfo.Type == ZKType.Node)
            //    {

            //        //var zk = this.GetZookeeper();
            //        if (zk.Exists(this.GetNodePath(nodeinfo.ServiceId, nodeinfo.SessionId), false) == null)
            //        {

            //            if (_nodeRemoved != null)
            //            {

            //                _nodeRemoved.Invoke();

            //            }
            //        }
            //    }
            //}
            catch (Exception exp)
            {

            }
            if (autoevent != null)
                autoevent.Set();
        }

        public override void Dispose()
        {
            isdisposeing = true;

            if (autoevent != null)
            {
                autoevent.Set();
                autoevent.Dispose();
            }

            base.Dispose();

        }
    }
}
